package actor

import java.io.File

import akka.actor.{Actor, ActorSystem, PoisonPill}
import akka.stream.Materializer
import command.{CommandExec, MissionUtils}
import dao._
import implicits.Implicits._
import javax.inject.Inject
import models.Tables._
import org.apache.commons.io.FileUtils
import org.joda.time.DateTime
import play.api.libs.json.Json
import shared.VarTool
import tool.Pojo._
import tool._
import utils.Utils

import scala.concurrent.ExecutionContext.Implicits.global
import scala.util.{Failure, Success}

/**
 * Created by Administrator on 2019/10/24
 */
class StepMissionExecActor @Inject()(mission: StepMissionRow)(implicit val system: ActorSystem,
                                                              implicit val materializer: Materializer,
                                                              implicit val stepMissionDao: StepMissionDao,
                                                              implicit val dao: MyDao
) extends Actor {

  val sampleDao = dao.sampleDao

  def stepSearch(workspaceDir: File) = {
    CommandExec().flatMap { b =>
      val userId = mission.userId
      val sampleId = mission.sampleId
      sampleDao.selectSiteInfoById(userId, sampleId).flatMap { case (id, map) =>
        val kitName = mission.kitName
        val siteNames = VarTool.siteNamesMap(kitName)
        val newMap = siteNames.map { siteName =>
          (siteName -> map.getOrElse(siteName, ""))
        }.toMap
        sampleDao.selectStep(userId, newMap, mission)
      }.flatMap { sampleIds =>
        val finalSampleIds = if (sampleIds.contains(mission.sampleId)) {
          sampleIds
        } else {
          mission.sampleId :: sampleIds
        }
        val newMission = mission.copy(result = Some(finalSampleIds))
        stepMissionDao.update(newMission)
      }
    }
  }

  override def receive: Receive = {
    case "run" =>
      val newMision = mission.copy(state = "running")
      val userId = mission.userId
      val outDir = Tool.getUserStepMissionDir(mission.userId)
      val missionDir = MissionUtils.getMissionDir(mission.id, outDir)
      val (workspaceDir, resultDir) = (missionDir.workspaceDir, missionDir.resultDir)
      val logFile = Tool.getLogFile(workspaceDir.getParentFile)
      stepMissionDao.update(newMision).map { x =>
        val commandExec = stepSearch(workspaceDir)
        val state = if (commandExec.isSuccess) {
          "success"
        } else {
          commandExec.errorInfo.toFile(logFile)
          "error"
        }
        stepMissionDao.select(mission.id).flatMap { mission =>
          val newMission = mission.copy(state = state, endTime = Some(new DateTime()))
          stepMissionDao.update(newMission)
        }.map { x =>
        }
      }.onComplete {
        case Failure(exception) =>
          exception.printStackTrace()
          FileUtils.writeStringToFile(logFile, exception.toString)
          val newMission = mission.copy(state = "error", endTime = Some(new DateTime()))
          stepMissionDao.update(newMission).map { x =>
          }
          self ! "stop"
        case Success(x) =>
          self ! "stop"
      }

    case "stop" =>
      self ! PoisonPill

  }
}
